#include "old5m3x.h"
#include "usart1.h"
#include "led.h"
#include "dac1.h"
#include "tim5.h"

/*
从机开机,可接受的命令
    COMMUNICATIONTEST(带ID):      返回 COMMUNICATIONTEST
    INFRAREDTEST(带ID):           光线未拦断就返回 INFRAREDTEST
    TESTOVER:(带ID):              测试结束
    IRPOSITIONTEST(带ID):         进入PositionTest,通断变化时发一条消息
                                        收到 STARTWORK 点亮灯，开始工作
                                        收到 STOPWORK  熄灭灯，停止工作
                                        收到 RESTART*4 重新开始
                                        返回 REACHED   状态变化为拦断时，一直拦断不重复返回
                                        返回 LEAVED    状态变化为接通时,一直接通不重复返回

B 传感器：
    TESTOVER(带ID):              测试结束，后进入反射程序
    STARTWORK(带ID):             不管收到发射桩的启动信号还是反射桩的启动信号都会开始工作
    STOPWORK(带ID):              收到反射桩的停止信号才会停止工作
    RESTART*4(带ID):             重启传感器，收到后传感器进入测试循环


*/
void restart_all()
{
    // 给传感器发送 RESTART*4 为什么要发5条才能生启呢？
    USART1_SendMsg_By_485_Without_Stopbit(revert8bit(RESTART));
    USART1_SendMsg_By_485_Without_Stopbit(revert8bit(RESTART));
    USART1_SendMsg_By_485_Without_Stopbit(revert8bit(RESTART));
    USART1_SendMsg_By_485_Without_Stopbit(revert8bit(RESTART));
    // 等待从机重启
    Delay_ms(500);
}
void restart_and_enter_workmode()
{
    // 重启所有传感器
    restart_all();
    // 给所有传感器发送 SETWORKTIME 命令
    USART1_SendMsg_By_485_Without_Stopbit(revert8bit(SETWORKTIME));
    Delay_us(300);
    // 给所有传感器发送工作时间
    USART1_SendMsg_By_485_Without_Stopbit(revert8bit(4000 / 100));
    Delay_us(300);
    // 给传感器发送 TESTOVER 命令
    for (uint8_t id = 1; id <= 6; id++)
    {
        USART1_SendMsg_By_485_Without_Stopbit(revert8bit(MergeMsg(GetReflectID(id), TESTOVER)));
        Delay_us(300);
        USART1_SendMsg_By_485_Without_Stopbit(revert8bit(MergeMsg(id, TESTOVER)));
        Delay_us(300);
    }
}

void enter_IR_position_test_mode(uint8_t id)
{
    // B传感器 开始正式工作
    USART1_SendMsg_By_485_Without_Stopbit(revert8bit(MergeMsg(GetReflectID(id), TESTOVER)));
    Delay_us(300);

    // A传感器 进光线测试 B看到了STARTWORK命令也会开始反射
    USART1_SendMsg_By_485_Without_Stopbit(revert8bit(MergeMsg(id, IRPOSITIONTEST)));
    Delay_us(300);
    USART1_SendMsg_By_485_Without_Stopbit(revert8bit(MergeMsg(id, STARTWORK)));
    Delay_us(300);
}

void exit_IR_position_test_mode(uint8_t id)
{
    // A传感器 停止工作,如果发送消息时，A正在发射信号，则要等上10ms，等收到信号再说
    USART1_SendMsg_By_485_Without_Stopbit(revert8bit(MergeMsg(id, STOPWORK)));
    Delay_ms(10);
    // 停止工作，B已进入正式工作除了重启不会再进入测试循环
    USART1_SendMsg_By_485_Without_Stopbit(revert8bit(MergeMsg(GetReflectID(id), STOPWORK)));
    Delay_ms(10);
}

void Old5m3x_display_online_status()
{
    // 8 4 2 1 8 4 2 1  8 4 2 1 8 4 2 1
    // 0 0 1 1 1 1 1 1  0 0 1 1 1 1 1 1
    //    3       F        3       F
    // 高8位每一位代表一个传感器
    // 低8位每一位代表一个反射传感器
    uint8_t msg = 0;
    uint16_t online = 0;      // 用16位变量记录传感器在线状态（高8位A传感器，低8位B传感器）
    uint16_t last_online = 0; // 记录上一次的在线状态
    uint16_t msg_count = 0;   // 记录发消息数目

    // 初始化显示：在屏幕显示1-6数字
    static_display_mode();
    restart_all();

    for (uint8_t i = 1; i <= 6; i++)
    {
        led_print_one_ascii(i + '0', i - 1);
    }

    // 主循环：持续扫描传感器状态
    while (1)
    {
        last_online = online;
        for (uint8_t i = 1; i <= 6; i++)
        {
            // 显示消息数目
            Display16bit(15, 6, ++msg_count);

            // A传感器
            msg = MergeMsg(i, COMMUNICATIONTEST);
            USART1_SendMsg_By_485_Without_Stopbit(revert8bit(msg));
            if (Delay_us_with_Break_by_Function(3000, has_new_msg_received) && (USART1->DR == revert8bit(msg)))
            {
                Display8bit(0, i - 1, 0x7E);
                online |= (1 << ((i - 1) + 8));
            }
            else
            {
                Display8bit(0, i - 1, 0x00);
                online &= ~(1 << ((i - 1) + 8));
            }

            // B传感器
            msg = MergeMsg(GetReflectID(i), COMMUNICATIONTEST);
            USART1_SendMsg_By_485_Without_Stopbit(revert8bit(msg));
            if (Delay_us_with_Break_by_Function(3000, has_new_msg_received) && (USART1->DR == revert8bit(msg)))
            {
                Display8bit(15, i - 1, 0x7E);
                online |= (1 << ((i - 1) + 0));
            }
            else
            {
                Display8bit(15, i - 1, 0x00);
                online &= ~(1 << ((i - 1) + 0));
            }
        }
        // 有变化就发出声音
        if (online != last_online)
        {
            dac1_play_by_index(SND_783HZ, 0);
        }

        // 全在线就退出
        if (online == 0x3F3F)
        {
            Delay_ms(500);
            break;
        }
    }
}

void Old_5m3x()
{
    uint8_t msg = 0, is3Reached = 0, isLetFirstWork = 0;
    uint16_t time[6] = {0, 0, 0, 0, 0, 0};
    // 初始化
    restart_and_enter_workmode();
    // 清屏
    led_clear_display_buf();
    display_static_text((uint8_t *)str_old_5m3x_05);
    Delay_ms(100);
    // 给1号传感器发送 STARTWORK
    USART1_SendMsg_By_485_Without_Stopbit(revert8bit(MergeMsg(1, STARTWORK)));
    isLetFirstWork = 1;
    while (1)
    {
        // 等待返回消息
        if (has_new_msg_received())
        {
            msg = USART1->DR;
            msg = revert8bit(msg);
            switch (GetMsgStyle(msg))
            {
            case REACHED:
                // 1号到达，显示准备开始
                // 2 3 4 5 号到达
                // 6 号到达，停表
                switch (GetIDFromMsg(msg))
                {
                case 1:
                    // 1号到达，显示准备开始
                    watch(WatchReset);
                    dac1_play_by_index(SND_READY, 1);
                    break;

                case 2:
                    time[0] = watch(WatchGetTime);
                    dac1_play_by_index(SND_783HZ, 1);
                    Delay_ms(700);
                    USART1_SendMsg_By_485_Without_Stopbit(revert8bit(MergeMsg(3, STARTWORK)));
                    break;

                case 3:
                    if (is3Reached == 0)
                    {
                        time[1] = watch(WatchGetTime);
                    }
                    else
                    {
                        time[3] = watch(WatchGetTime);
                    }
                    dac1_play_by_index(SND_783HZ, 1);
                    Delay_ms(700);
                    if (is3Reached == 0)
                    {
                        USART1_SendMsg_By_485_Without_Stopbit(revert8bit(MergeMsg(4, STARTWORK)));
                        is3Reached = 1;
                    }
                    else
                    {
                        USART1_SendMsg_By_485_Without_Stopbit(revert8bit(MergeMsg(5, STARTWORK)));
                    }
                    break;

                case 4:
                    time[2] = watch(WatchGetTime);
                    dac1_play_by_index(SND_783HZ, 1);
                    Delay_ms(700);
                    USART1_SendMsg_By_485_Without_Stopbit(revert8bit(MergeMsg(3, STARTWORK)));
                    break;

                case 5:
                    time[4] = watch(WatchGetTime);
                    dac1_play_by_index(SND_783HZ, 1);
                    Delay_ms(700);
                    USART1_SendMsg_By_485_Without_Stopbit(revert8bit(MergeMsg(6, STARTWORK)));
                    break;

                case 6:
                    // 6号到达，停表 结束测试，重新让1号工作
                    watch(WatchStop);
                    time[5] = watch(WatchGetTime);
                    dac1_play_by_index(SND_783HZ, 1);
                    // 清除秒字
                    led_print_one_ascii(' ', 6);
                    led_print_one_ascii(' ', 7);
                    // 显示每道时间
                    for (uint8_t i = 0; i < 6; i++)
                    {
                        uint16_t tmp = i == 0 ? (time[i] - 70) / 6 : (time[i] - time[i - 1] - 70) / 6;
                        tmp = tmp == 0 ? 1 : tmp;
                        tmp = tmp > 16 ? 16 : tmp;
                        Display16bit(i * 2 + 2, 6, 0xFFFF << (16 - tmp));
                    }
                    Delay_ms(300);
                    speak_time(watch(WatchGetTime));
                    USART1_SendMsg_By_485_Without_Stopbit(revert8bit(MergeMsg(1, STARTWORK)));
                    break;
                }
                break;

            case TIMEOVER:
                // 结束测试，重新让1号工作
                watch(WatchStop);
                dac1_play_by_index(SND_TEC, 1);
                Delay_ms(200);
                USART1_SendMsg_By_485_Without_Stopbit(revert8bit(MergeMsg(1, STARTWORK)));
                break;

            case LEAVED:
                // 从1号离开，开始计表
                watch(WatchStart);
                is3Reached = 0;
                isLetFirstWork = 0;
                dac1_play_by_index(SND_783HZ, 1);
                Delay_ms(700);
                USART1_SendMsg_By_485_Without_Stopbit(revert8bit(MergeMsg(2, STARTWORK)));
                break;
            }
        }
        else if ((watch(WatchGetTime) > 2000) && (isLetFirstWork == 0))
        {
            // 20秒没收到消息，重新让1号工作
            watch(WatchStop);
            dac1_play_by_index(SND_TEC, 1);
            Delay_ms(1000);
            display_static_text((uint8_t *)str_old_5m3x_04);
            Delay_ms(1000);
            display_static_text((uint8_t *)str_old_5m3x_05);
            Delay_ms(1000);
            USART1_SendMsg_By_485_Without_Stopbit(revert8bit(MergeMsg(1, STARTWORK)));
            isLetFirstWork = 1;
        }
    }
}

void Old5m3x_light_test()
{
    uint8_t id = 2, msg = 0;
    // 初始化显示：在屏幕显示1-6数字, 重启所有传感器
    restart_all();
    static_display_mode();
    for (uint8_t i = 1; i <= 6; i++)
    {
        led_print_one_ascii(i + '0', i - 1);
    }

    while (1)
    {
        // 测试一对
        dac1_play_digit(id);
        Display8bit(14, id - 1, 0x7E);
        enter_IR_position_test_mode(id);
        tim5_start_timer(0);
        while (tim5_read_started_time_us(0) <= 5000000)
        {
            if (has_new_msg_received())
            {
                // 收到REACHED
                msg = USART1->DR;
                if ((GetMsgStyle(revert8bit(msg)) == REACHED) && (GetIDFromMsg(revert8bit(msg)) == id))
                {
                    dac1_play_by_index(SND_783HZ, 0);
                    Display16bit(id - 1, 6, 0xFFFF);
                }
                // 收到LEAVED
                else if ((GetMsgStyle(revert8bit(msg)) == LEAVED) && (GetIDFromMsg(revert8bit(msg)) == id))
                {
                    Display16bit(id - 1, 6, 0x0000);
                }
            }
        }
        exit_IR_position_test_mode(id);
        Display16bit(id - 1, 6, 0x0000);
        Display8bit(14, id - 1, 0x00);

        // 下一个传感器,只有2-5号
        id = id < 5 ? id + 1 : 2;

        // 1号被踩到，退出测试
        Display8bit(14, 1 - 1, 0x7E);
        enter_IR_position_test_mode(1);
        tim5_start_timer(0);
        while (tim5_read_started_time_us(0) <= 100000)
        {
            if (has_new_msg_received())
            {
                // 收到REACHED
                msg = USART1->DR;
                return;
                if ((GetMsgStyle(revert8bit(msg)) == REACHED) && (GetIDFromMsg(revert8bit(msg)) == 1))
                {
                    exit_IR_position_test_mode(1);
                    Delay_ms(500);
                    return;
                }
            }
        }
        exit_IR_position_test_mode(1);
        Display8bit(14, 1 - 1, 0x00);
    }
}

void poweron_sequence_for_old5m3x()
{
    led_display_infomation_and_wait_once((uint8_t *)str_old_5m3x_01); // 显示仪器名称 五三测试仪(兼容旧传感器)
    dac1_play_by_index(SND_440HZ, 1);                          // 提示音
    usart1_init_without_IRQ(4715);                             // 1K通讯
    // 静态显示
    static_display_mode();
    // 发送期间也可以刷新屏幕
    stop_refresh_led_while_usart_send = 0;

    // 显示在线的传感器情况, 并等待12个传感器在线时退出
    led_display_infomation_and_wait_once((uint8_t *)str_old_5m3x_02);
    Old5m3x_display_online_status();
    // 循环1-6有遮挡就发出声音,调试光线位置,直到1号全程被阻挡时退出
    led_display_infomation_and_wait_once((uint8_t *)str_old_5m3x_03);
    Old5m3x_light_test();
    // 进入测试模式
    Old_5m3x();
}
